package org.dcarew.clearcase;


import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;

// TODO: public IMoveDeleteHook getMoveDeleteHook() {

// TODO: public FileModificationValidator getFileModificationValidator2() {

/**
 *  
 * 
 * @author Devon Carew
 */
public class CCRepositoryProvider extends RepositoryProvider
{
    public static final String PROVIDER_ID = "org.dcarew.clearcase.repositoryProvider";


    private static final String DB_FILENAME = ".copyarea.db";
    
    private static final String DAT_FILENAME = ".copyarea.dat";
    
    private Map<String, DBFileInfo> dbInfoMap = new HashMap<String, DBFileInfo>();
    

    /**
     * 
     */
    public CCRepositoryProvider()
    {
        
    }





    public static boolean isClearCaseRepository(IProject project)
    {
        if (project == null)
            return false;

        if (!isShared(project))
            return false;

        return getProvider(project, PROVIDER_ID) != null;
    }





    public static void setSharing(IProject project, /* FolderSyncInfo info, */IProgressMonitor monitor) throws TeamException
    {
        // Ensure provided info matches that of the project

        // Ensure that the provided location is managed

        // Register the project with Team
        RepositoryProvider.map(project, PROVIDER_ID);
    }





    @Override
    public String getID()
    {
        return PROVIDER_ID;
    }





    @Override
    public void configureProject() throws CoreException
    {

    }





    @Override
    public void deconfigure() throws CoreException
    {

    }





    public CCSyncInfo getSyncInfo(IResource resource)
    {
        CCSyncInfo syncInfo = new CCSyncInfo(resource);
        
        try
        {
            if (resource instanceof IFile)
            {
                IFile file = (IFile)resource;
                IContainer container = file.getParent();
                
                if (isHiddenFile(file))
                    return null;
                
                IFile dbFile = container.getFile(new Path(DB_FILENAME));
                
                if (dbFile.exists())
                {
                    fillInInfoFor(resource, dbFile, syncInfo);
                }
            }
            else if (resource instanceof IContainer)
            {
                File dir = resource.getLocation().toFile();
                
                File dbFile = new File(dir.getParentFile(), DB_FILENAME);
                
                if (dbFile.exists())
                {
                    fillInInfoFor(resource, dbFile, syncInfo);
                }
            }
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
        
        return syncInfo;
    }




    public boolean isHiddenFile(IFile file)
    {
        if (DB_FILENAME.equals(file.getName()) || DAT_FILENAME.equals(file.getName()))
            return true;
        
        return false;
    }





    public CCSyncInfo getSyncInfoRecursive(IContainer container)
    {
        CCSyncInfo syncInfo = getSyncInfo(container);
        
        if (syncInfo == null)
            return null;
        
        try
        {
            if (syncInfo.isUnderRevisionControl() && !syncInfo.isDirty())
            {
                for (IResource resource : container.members())
                {
                    if (resource.isTeamPrivateMember() || resource.isDerived())
                        continue;
                    
                    if ((resource instanceof IFile) && isHiddenFile((IFile)resource))
                        continue;
                    
                    CCSyncInfo childInfo;
                    
                    if (resource instanceof IContainer)
                    {
                        childInfo = getSyncInfoRecursive((IContainer)resource);
                    }
                    else
                    {
                        childInfo = getSyncInfo(resource);
                    }
                    
                    if (childInfo == null)
                        continue;
                    
                    if (childInfo.isDirty() || childInfo.isUnknown())
                    {
                        syncInfo.setDirty(true);
                        
                        break;
                    }
                }
            }
            else if (!syncInfo.isUnderRevisionControl())
            {
                if (container.members().length == 0)
                {
                    syncInfo.setDirty(false);
                }
            }
        }
        catch (CoreException ce)
        {
            // TODO:
            
            ce.printStackTrace();
        }
        
        return syncInfo;
    }


    public String getViewName(IProject project)
    {
        // Look for a file named DAT_FILENAME in a parent directory.
        
        File dir = project.getLocation().toFile();
        
        while (dir != null && dir.isDirectory() && dir.canRead())
        {
            File datFile = new File(dir, DAT_FILENAME);
            
            if (datFile.exists())
            {
                return getViewName(datFile);
            }
            else
            {
                dir = dir.getParentFile();
            }
        }
        
        return null;
    }


    private String getViewName(File datFile)
    {
        DatFileInfo info = new DatFileInfo(datFile);
        
        return info.getViewName();
    }




    private void fillInInfoFor(IResource resource, IFile dbFile, CCSyncInfo syncInfo)
        throws IOException
    {
        fillInInfoFor(resource, dbFile.getLocation().toFile(), syncInfo);
    }
    
    private void fillInInfoFor(IResource resource, File dbFile, CCSyncInfo syncInfo)
        throws IOException
    {
        String path = dbFile.getCanonicalPath();
        DBFileInfo dbInfo = null;
        
        if (dbInfoMap.containsKey(path))
        {
            dbInfo = dbInfoMap.get(path);
            
            if (dbInfo.getLastModified() != dbFile.lastModified())
            {
                dbInfo = new DBFileInfo(dbFile);
                dbInfoMap.put(path, dbInfo);
            }
        }
        else
        {
            dbInfo = new DBFileInfo(dbFile);
            dbInfoMap.put(path, dbInfo);
        }
        
        DBFileEntry entry = dbInfo.getFileEntry(resource);
        
        if (entry != null)
        {
            syncInfo.setUnderRevisionControl(true);
            
            if (entry.isCheckedOut())
                syncInfo.setCheckedOut(true);
            else if (entry.isHijacked())
                syncInfo.setDirty(true);
        }
        else
        {
            //syncInfo.setDirty(true);
        }
    }

}
